/*
 * app_key_value.c
 *
 *  Created on: 2023年7月28日
 *      Author: mcealt_DS
 */
#include "app_key_value.h"
#include "circular_buffer.h"
#include "stdbool.h"
#include "stddef.h"

Buffer_t buff_key_value_down; // 下行物模型队列
Buffer_t buff_key_value_up;   // 上行物模型队列

// 检查ID是否存在
app_key_value_err_e checkKeyId(KEY_VALUE_ID_E kedId)
{
    app_key_value_err_e ret = APP_KEY_VALUE_NO_ERR;
    switch (kedId)
    {
    // 配置状态输出
    case APP_KEY_VALUE_ID_SPVN_SLOT_TIME:     // 0x01,
    case APP_KEY_VALUE_ID_GLOBAL_SLOT_MALLOC: // 0x02,
    case APP_KEY_VALUE_ID_GROUP_IDX:          // 0x03,
    case APP_KEY_VALUE_ID_INIT_PREAMBLE_SET:  // 0x04,
    case APP_KEY_VALUE_ID_WHITE_BLACK_CHAN:   // 0x05,
    case APP_KEY_VALUE_ID_LAST_TXD_TIMESTAMP: // 0x06,
    case APP_KEY_VALUE_ID_ADD_SLOT_TYPE:      // 0x07,
    // 指令操作输出，若通过应答下行必须使用 Aseq 字段 确保可靠传输及过滤重复数据
    case APP_KEY_VALUE_ID_DEBUG_CRTL:  // 0x0A,
    case APP_KEY_VALUE_ID_DEVICE_INFO: // 0x0D,
    case APP_KEY_VALUE_ID_DEBUG_INFO:  // 0x0F,
    // 状态输入
    case APP_KEY_VALUE_ID_INPUT_OUTPUT:  // 0x10,
    case APP_KEY_VALUE_ID_IN_OUTPUT_VAR: // 0x11,
    case APP_KEY_VALUE_ID_TEMP_HUMI:     // 0x12,
    case APP_KEY_VALUE_ID_VOLT_C:        // 0x13,
    case APP_KEY_VALUE_ID_RUNTIME:       // 0x14,
    case APP_KEY_VALUE_ID_ACKCTRLRECVD:  // 0x2E,
    case APP_KEY_VALUE_ID_BCASTRECVD:    // 0x2F,
    // 操作输入
    case APP_KEY_VALUE_ID_KEY_PRESS:       // 0x30,
    case APP_KEY_VALUE_ID_KEY_MULTI_PRESS: // 0x31,
    case APP_KEY_VALUE_ID_TAG_SCAN:        // 0x32,
    case APP_KEY_VALUE_ID_PICTURE_CAPTURE: // 0x3A,
    case APP_KEY_VALUE_ID_UPDATEME:        // 0X4F,
    // 配置状态输出，配置外设所处的状态，如开、关，亮、灭等状态，以及其他配置参数
    case APP_KEY_VALUE_ID_OPTION:     // 0x50,
    case APP_KEY_VALUE_ID_OPTION_VAR: // 0x51,
    // 指令操作输出，若通过应答下行必须使用 Aseq 字段 确保可靠传输及过滤重复数据，并同时直接自动修改 OPTION 相应的状态量
    case APP_KEY_VALUE_ID_COMLED_CTRL:   // 0x60,
    case APP_KEY_VALUE_ID_OPERATE_CTRL:  // 0x61,
    case APP_KEY_VALUE_ID_KEY_VALUE_GET: // 0x70,
    // 调试字段
    case APP_KEY_VALUE_ID_PLUG_DEBUG_DATA: // 0xE0,
    // 文件传输
    case APP_KEY_VALUE_ID_FILE_CHECK_RET:     // 0xFB,
    case APP_KEY_VALUE_ID_FILE_TRANS_CONFIRM: // 0xFD,
    case APP_KEY_VALUE_ID_FILE_TRANS_ACCEPT:  // 0xFE,
    case APP_KEY_VALUE_ID_FILE_TRANS_REQ:     // 0xFF,
        ret = APP_KEY_VALUE_NO_ERR;
        break;
    default:
        ret = APP_KEY_VALUE_ERR_ID;
        break;
    }
    return ret;
}

// get物模型数据长度
uint8_t get_key_value_size(KEY_VALUE_ID_E kedId)
{
    switch (kedId)
    {
        // 配置状态输出
    case APP_KEY_VALUE_ID_SPVN_SLOT_TIME: // 0x01,
        return APP_KEY_VALUE_ID_SPVN_SLOT_TIME_SIZE;
        break;
    case APP_KEY_VALUE_ID_GLOBAL_SLOT_MALLOC: // 0x02,
        return APP_KEY_VALUE_GLOBAL_SLOT_MALLOC_SIZE;
        break;
    case APP_KEY_VALUE_ID_GROUP_IDX: // 0x03,
        return APP_KEY_VALUE_GROUP_IDX_SIZE;
        break;
    case APP_KEY_VALUE_ID_INIT_PREAMBLE_SET: // 0x04,
        return APP_KEY_VALUE_INIT_PREAMBLE_SET_SIZE;
        break;
    case APP_KEY_VALUE_ID_WHITE_BLACK_CHAN: // 0x05,
        return APP_KEY_VALUE_WHITE_BLACK_CHAN_SIZE;
        break;
    case APP_KEY_VALUE_ID_LAST_TXD_TIMESTAMP: // 0x06,
        return APP_KEY_VALUE_LAST_TXD_TIMESTAMP_SIZE;
        break;
    case APP_KEY_VALUE_ID_ADD_SLOT_TYPE: // 0x07,
        return APP_KEY_VALUE_ADD_SLOT_TYPE_SIZE;
        break;
        // 指令操作输出，若通过应答下行必须使用 Aseq 字段 确保可靠传输及过滤重复数据
    case APP_KEY_VALUE_ID_DEBUG_CRTL: // 0x0A,
        return APP_KEY_VALUE_DEBUG_CRTL_SIZE;
        break;
    case APP_KEY_VALUE_ID_DEVICE_INFO: // 0x0D,
        return APP_KEY_VALUE_DEVICE_INFO_SIZE;
        break;
    case APP_KEY_VALUE_ID_DEBUG_INFO: // 0x0F,
        return APP_KEY_VALUE_DEBUG_INFO_SIZE;
        break;
        // 状态输入
    case APP_KEY_VALUE_ID_INPUT_OUTPUT: // 0x10,
        return APP_KEY_VALUE_INPUT_OUTPUT_SIZE;
        break;
    case APP_KEY_VALUE_ID_IN_OUTPUT_VAR: // 0x11,
        return APP_KEY_VALUE_IN_OUTPUT_VAR_SIZE;
        break;
    case APP_KEY_VALUE_ID_TEMP_HUMI: // 0x12,
        return APP_KEY_VALUE_TEMP_HUMI_SIZE;
        break;
    case APP_KEY_VALUE_ID_VOLT_C: // 0x13,
        return APP_KEY_VALUE_VOLT_C_SIZE;
        break;
    case APP_KEY_VALUE_ID_RUNTIME: // 0x14,
        return APP_KEY_VALUE_ID_RUNTIME_SIZE;
        break;
    case APP_KEY_VALUE_ID_ACKCTRLRECVD: // 0x2E,
        return APP_KEY_VALUE_ACKCTRLRECVD_SIZE;
        break;
    case APP_KEY_VALUE_ID_BCASTRECVD: // 0x2F,
        return APP_KEY_VALUE_BCASTRECVD_SIZE;
        break;
        // 操作输入
    case APP_KEY_VALUE_ID_KEY_PRESS: // 0x30,
        return APP_KEY_VALUE_KEY_PRESS_SIZE;
        break;
    case APP_KEY_VALUE_ID_KEY_MULTI_PRESS: // 0x31,
        return APP_KEY_VALUE_KEY_MULTI_PRESS_SIZE;
        break;
    case APP_KEY_VALUE_ID_TAG_SCAN: // 0x32,
        return APP_KEY_VALUE_TAG_SCAN_SIZE;
        break;
    case APP_KEY_VALUE_ID_PICTURE_CAPTURE: // 0x3A,
        return APP_KEY_VALUE_PICTURE_CAPTURE_SIZE;
        break;
    case APP_KEY_VALUE_ID_UPDATEME: // 0X4F,
        return APP_KEY_VALUE_SIZE_IS_AVR;
        break;
        // 配置状态输出，配置外设所处的状态，如开、关，亮、灭等状态，以及其他配置参数
    case APP_KEY_VALUE_ID_OPTION: // 0x50,
        return APP_KEY_VALUE_OPTION_SIZE;
        break;
    case APP_KEY_VALUE_ID_OPTION_VAR: // 0x51,
        return APP_KEY_VALUE_OPTION_VAR_SIZE;
        break;
        // 指令操作输出，若通过应答下行必须使用 Aseq 字段 确保可靠传输及过滤重复数据，并同时直接自动修改 OPTION 相应的状态量
    case APP_KEY_VALUE_ID_COMLED_CTRL: // 0x60,
        return APP_KEY_VALUE_COMLEDCTRL_SIZE;
        break;
    case APP_KEY_VALUE_ID_OPERATE_CTRL: // 0x61,
        return APP_KEY_VALUE_OPERATECTRL_SIZE;
        break;
    case APP_KEY_VALUE_ID_KEY_VALUE_GET: // 0x70,
        return APP_KEY_VALUE_KEYVALUEGET_SIZE;
        break;
        // 调试字段
    case APP_KEY_VALUE_ID_PLUG_DEBUG_DATA: // 0xE0, 自测会用，长度可变
        return APP_KEY_VALUE_SIZE_IS_AVR;
        break;
        // 文件传输
    case APP_KEY_VALUE_ID_FILE_CHECK_RET: // 0xFB,
        return APP_KEY_VALUE_SIZE_IS_AVR;
        break;
    case APP_KEY_VALUE_ID_FILE_TRANS_CONFIRM: // 0xFD,
        return APP_KEY_VALUE_SIZE_IS_AVR;
        break;
    case APP_KEY_VALUE_ID_FILE_TRANS_ACCEPT: // 0xFE,
        return APP_KEY_VALUE_SIZE_IS_AVR;
        break;
    case APP_KEY_VALUE_ID_FILE_TRANS_REQ: // 0xFF,
        return AAPP_KEY_VALUE_ID_FILE_TRANS_REQ_SIZE;
        break;
    default:
        return APP_KEY_VALUE_SIZE_IS_AVR; // 新物模型都为不定长，返回0xFF的风险很大
        break;
    }
}

// 物模型队列初始化
void app_key_value_init(void)
{
    bufferInit(&buff_key_value_down, BUFF_KEY_VALUE_SIZE);
    bufferInit(&buff_key_value_up, BUFF_KEY_VALUE_SIZE);
}

// 生产物模型(不区分角色)
app_key_value_err_e set_key_value(const keyValue_t *keyValue)
{
    uint8_t value_size = 0;
#ifdef HUB_DEVICE // 生产下行
    Buffer_t *pBuffer = &buff_key_value_down;
#elif defined(RFM_DEVICE) // 生产上行
    Buffer_t *pBuffer = &buff_key_value_up;
#endif
    if (checkKeyId(keyValue->id) == APP_KEY_VALUE_ERR_ID)
    {
        return APP_KEY_VALUE_ERR_ID; // 物模型ID未知
    }
    value_size = get_key_value_size(keyValue->id);
    if (value_size == 0)
    {
        return APP_KEY_VALUE_ERR_VALUE_LEN; // 数据长度未知
    }
    else // 正常
    {
        if (pBuffer->count + keyValue->valueSize + 1 > pBuffer->size)
        {
            return APP_KEY_VALUE_ERR_FULL; // 缓存已满
        }

        bufferAdd(pBuffer, keyValue->id);
        // printf("set kv:%02X",keyValue->id);//打印set物模型的数据
        for (uint16_t i = 0; i < keyValue->valueSize; i++)
        {
            bufferAdd(pBuffer, keyValue->value[i]);
            // printf("%02X",keyValue->value[i]);
        }
        // printf("\r\n");
    }

    return APP_KEY_VALUE_NO_ERR;
}

// 消费物模型(不区分角色)
app_key_value_err_e get_key_value(keyValue_t *keyValue)
{
#ifdef HUB_DEVICE // 消费上行
    Buffer_t *pBuffer = &buff_key_value_up;
#elif defined(RFM_DEVICE) // 消费下行
    Buffer_t *pBuffer = &buff_key_value_down;
#endif

    app_key_value_err_e ret = APP_KEY_VALUE_NO_ERR;
    uint8_t *data = NULL;

    if (pBuffer->count == 0)
        ret = APP_KEY_VALUE_ERR_NO_DATA;
    else
    {
        data = bufferRemove(pBuffer);
        keyValue->id = data[0];
        if (checkKeyId(keyValue->id) == APP_KEY_VALUE_ERR_ID)
        {
            pBuffer->count = 0;          // 清物模型队列
            return APP_KEY_VALUE_ERR_ID; // 物模型ID未知
        }
        keyValue->valueSize = get_key_value_size(keyValue->id);
        if (keyValue->valueSize == 0) //Bug0430变长物模型将返回ff，此处不可能返回0x00，参考rfm_set_key_value写法，对长度的判断
        {
            pBuffer->count = 0;                 // 清物模型队列
            return APP_KEY_VALUE_ERR_VALUE_LEN; // 数据长度未知
        }
        else if (keyValue->valueSize > pBuffer->count)
        {
            pBuffer->count = 0;            // 清物模型队列
            ret = APP_KEY_VALUE_ERR_VALUE; // 数据长度错误
        }
        else // 正常
        {
            for (uint16_t i = 0; i < keyValue->valueSize; i++)//Bug0430 风险很大，hub返回变长物模型将异常
            {
                data = bufferRemove(pBuffer);
                keyValue->value[i] = data[0];
            }
        }
    }
    return ret;
}
#ifdef HUB_DEVICE
app_key_value_err_e clean_hub_down_key_value(void)
{
    Buffer_t *pBuffer = &buff_key_value_down;
    pBuffer->count = 0;
    return APP_KEY_VALUE_NO_ERR;
}
app_key_value_err_e clean_hub_up_key_value(void)
{
    Buffer_t *pBuffer = &buff_key_value_up;
    pBuffer->count = 0;
    return APP_KEY_VALUE_NO_ERR;
}
#elif defined(RFM_DEVICE) // 消费下行
app_key_value_err_e clean_rfm_down_key_value(void)
{
    Buffer_t *pBuffer = &buff_key_value_down;
    pBuffer->count = 0;
    return APP_KEY_VALUE_NO_ERR;
}
app_key_value_err_e clean_rfm_up_key_value(void)
{
    Buffer_t *pBuffer = &buff_key_value_up;
    pBuffer->count = 0;
    return APP_KEY_VALUE_NO_ERR;
}
#endif
bool is_buff_key_value_down_empty(void)
{
    return bufferIsEmpty(&buff_key_value_down);
}

bool is_buff_key_value_up_empty(void)
{
    return bufferIsEmpty(&buff_key_value_up);
}

// 物模型解报:生产物模型队列
app_key_value_err_e app_key_value_unpack(uint8_t *keyValue_packet, uint16_t keyValue_packet_size)
{
#ifdef HUB_DEVICE // 生产上行
    Buffer_t *pBuffer = &buff_key_value_up;
#elif defined(RFM_DEVICE) // 生产下行
    Buffer_t *pBuffer = &buff_key_value_down;
#endif
    for (uint8_t i = 0; i < keyValue_packet_size; i++)
    {
        bufferAdd(pBuffer, keyValue_packet[i]);
    }
}

// 物模型组报:消费物模型队列
app_key_value_err_e app_key_value_pack(uint8_t *keyValue_packet, uint16_t *keyValue_packet_size)
{
#ifdef HUB_DEVICE // 消费下行
    Buffer_t *pBuffer = &buff_key_value_down;
#elif defined(RFM_DEVICE) // 消费上行
    Buffer_t *pBuffer = &buff_key_value_up;
#endif
    uint8_t *data = NULL;
    uint16_t count = pBuffer->count;

    if (0 == pBuffer->count)
    {
        return APP_KEY_VALUE_ERR_NO_DATA;
    }
    for (uint16_t i = 0; i < count; i++)
    {
        data = bufferRemove(pBuffer);
        keyValue_packet[i] = data[0];
    }
    *keyValue_packet_size = count;
    return APP_KEY_VALUE_NO_ERR;
}
